package com.projecthost.boots;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlImage;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.projecthost.boots.model.Category;
import com.projecthost.boots.model.Product;
import com.projecthost.util.HtmlParser;

public class BootsProductCrawler {

    private final static Logger logger = LoggerFactory.getLogger(BootsProductCrawler.class);

    public static final String BOOTS_URL = "http://m.boots.com";

    private final HtmlParser htmlParser;

    public BootsProductCrawler(HtmlParser htmlParser) {
        this.htmlParser = htmlParser;
    }

    //
    //    public List<Product> getProducts() throws IOException {
    //        HtmlPage mainBootsBeautyPage = htmlParser.getHtmlPageFromUrl(BOOTS_URL, true);
    //
    //        //logger.debug(mainBootsBeautyPage.asText());
    //        HtmlDivision narrowResults = (HtmlDivision) mainBootsBeautyPage.getByXPath("//div[@class='narrowResults']").get(0);
    //        List<HtmlAnchor> ratingsLinks = (List<HtmlAnchor>) narrowResults.getByXPath("./div[3]//li/a");
    //        for (int i = 0; i < 5; i++) {
    //            HtmlAnchor ratingLink = ratingsLinks.get(i);
    //            HtmlPage currentPage = ratingLink.click();
    //            HtmlDivision resultsControls = (HtmlDivision) currentPage.getByXPath("//div[@class='productSearchResultsControls']")
    //                    .get(0);
    //            HtmlSelect resultsPerPage = (HtmlSelect) resultsControls.getByXPath(".//div[@class='resultsPerPage']/select").get(0);
    //            HtmlAnchor resultsPerPageButton = (HtmlAnchor) resultsControls.getByXPath(".//div[@class='resultsPerPage']/a").get(0);
    //            currentPage = resultsPerPage.setSelectedAttribute("60", true);
    //            currentPage = resultsPerPageButton.click();
    //            resultsControls = (HtmlDivision) currentPage.getByXPath("//div[@class='productSearchResultsControls']").get(0);
    //            HtmlSelect sorting = (HtmlSelect) resultsControls.getByXPath(".//div[@class='sortBy']/select").get(0);
    //            HtmlAnchor sortingButton = (HtmlAnchor) resultsControls.getByXPath(".//div[@class='sortBy']/a").get(0);
    //            currentPage = sorting.setSelectedAttribute("P_STAR_RATING|1", true);
    //            currentPage = sortingButton.click();
    //            List<HtmlDivision> products = (List<HtmlDivision>) currentPage.getByXPath("//div[contains(@class,'product_item')]");
    //            logger.info(products.toString());
    //        }
    //        return null;
    //
    //    }

    public List<Category> getCategories() {
        String url = "/mt/www.boots.com";
        return getCategories(url, true, 3);
    }

    protected List<Category> getCategories(String url, boolean withSubcategories, int maxFurtherLevels) {
        HtmlPage categoriesPage = htmlParser.getHtmlPageFromUrl(BOOTS_URL + url, false);
        List<Category> categories = new ArrayList<Category>();
        @SuppressWarnings("unchecked")
        List<HtmlDivision> categoriesDiv = (List<HtmlDivision>) categoriesPage
                .getByXPath("//div[contains(@class,'iphone_list')]");
        if (categoriesDiv.size() > 0) {
            DomNodeList<HtmlElement> categoriesElements = categoriesDiv.get(0).getElementsByTagName("a");
            for (HtmlElement categoryElement : categoriesElements) {
                HtmlAnchor categoryAnchor = (HtmlAnchor) categoryElement;
                String categoryWithCount = categoryAnchor.getTextContent();
                int indexOfCount = categoryWithCount.lastIndexOf("(");
                String categoryName = categoryWithCount;
                if (indexOfCount >= 0) {
                    categoryName = categoryWithCount.substring(0, indexOfCount).trim();
                }
                String categoryUrl = categoryAnchor.getHrefAttribute();
                List<Category> subCategories = new ArrayList<Category>();
                if (withSubcategories && maxFurtherLevels > 1) {
                    logger.info("Getting contents of category " + categoryName + " from " + categoryUrl);
                    subCategories = getCategories(categoryUrl, withSubcategories, maxFurtherLevels - 1);
                }
                categories.add(new Category(categoryName, categoryUrl, subCategories));
            }
        }
        return categories;
    }

    public List<Product> getRatedProductsInCategory(String url, boolean withSubcategories, int maxFurtherLevels) {

        HtmlPage currentPage = htmlParser.getHtmlPageFromUrl(BOOTS_URL + url, false);
        HtmlSelect sortSelect = (HtmlSelect) currentPage.getElementById("sortBy");
        sortSelect.setSelectedAttribute("DIM_BASIC_RECORD_TYPE_ID||P_STAR_RATING|1", true);
        HtmlSubmitInput sortButton = (HtmlSubmitInput) currentPage.getElementById("un_jtt_sortBy");
        try {
            currentPage = sortButton.click();
        } catch (IOException e) {
            logger.error("Failed to load page after clicking the button", e);
        }

        List<Product> products = new ArrayList<Product>();
        List<HtmlDivision> productDivs = (List<HtmlDivision>) currentPage.getByXPath("//div[@id='ProductViewListGrid']/div/div");
        for (HtmlDivision productDiv : productDivs) {
            HtmlAnchor productNameLink = (HtmlAnchor) productDiv.getElementsByAttribute("a", "class", "productName").get(0);
            String productName = productNameLink.getTextContent();
            String productUrl = productNameLink.getHrefAttribute();
            //            String priceText = 
            //            Float price = Float.parseFloat(priceText);
            DomNodeList<HtmlElement> productImages = productDiv.getElementsByTagName("img");
            HtmlImage productImage = (HtmlImage) productImages.get(0);

            HtmlImage starsImage = (HtmlImage) productImages.get(1);
            String starRating = starsImage.getAltAttribute();
            Float rating = Float.valueOf(starRating.substring(0, starRating.indexOf(" ")));
            products.add(new Product(productUrl, productName, rating, productImage.getSrcAttribute()));
        }
        return products;
    }
}
